package com.gla.giliair.service.impl;

import com.gla.giliair.entity.MOrder;
import com.gla.giliair.service.DelayService;
import com.gla.giliair.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Description:
 * @Author: Yingtian qian
 * @Date: 2021/8/27 14:57
 */
@Service
public class DelayServiceImpl implements DelayService {
    @Autowired
    private OrderService orderService;

    @Autowired
    private ExecutorService delayOrderExecutor;

    private final static DelayQueue<DelayElement<MOrder>> delayQueue = new DelayQueue<>();

    public void cancelOrderAfter(Integer minute, MOrder mOrder) {
        DelayElement<MOrder> orderDelayed = new DelayElement<>(minute, mOrder.getOrderId(), mOrder.getCreateTime().getTime(), mOrder);
        // 添加延迟任务：x min后取消订单
        delayQueue.put(orderDelayed);
        System.out.println("延时任务开始时间：" + DateFormat.getDateTimeInstance().format(new Date()));

        delayOrderExecutor.execute(() -> {
            System.out.println("启动处理的订单线程：" + Thread.currentThread().getName());
            while (!delayQueue.isEmpty()) {
                DelayElement<MOrder> orderTaken = null;
                try {
                    orderTaken = delayQueue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Map<String, Object> res = orderService.autoCancelOrder(orderTaken.data);
                System.out.println(res.toString());
                System.out.println("延时任务结束时间：" + DateFormat.getDateTimeInstance().format(new Date()));
            }
        });
    }

    public void cancelCancelOrderAfter(Long orderId) {
        // 取消延迟任务
        for (Iterator<DelayElement<MOrder>> iterator = delayQueue.iterator(); iterator.hasNext(); ) {
            DelayElement<MOrder> queue = iterator.next();
            if (queue.dataId.equals(orderId)) {
                delayQueue.remove(queue);
            }
        }
        System.out.println("取消延时任务时间：" + DateFormat.getDateTimeInstance().format(new Date()));
    }

    static class DelayElement<T> implements Delayed {

        /**
         * 延迟时间
         */
        private long delay;
        /**
         * 数据id
         */
        private Long dataId;
        /**
         * 开始时间
         */
        private long startTime;
        /**
         * 到期时间
         */
        private long expire;
        /**
         * 创建时间
         */
        private Date now;
        /**
         * 泛型data
         */
        private T data;

        public DelayElement(Long secondsDelay, Long dataId, long startTime, T data) {
            super();
            this.delay = secondsDelay * 1000;
            this.dataId = dataId;
            this.startTime = startTime;
            this.expire = startTime + delay;
            this.now = new Date();
            this.data = data;
        }

        public DelayElement(Integer minutesDelay, Long dataId, long startTime, T data) {
            super();
            this.delay = minutesDelay * 60 * 1000L;
            this.dataId = dataId;
            this.startTime = startTime;
            this.expire = startTime + delay;
            this.now = new Date();
            this.data = data;
        }

        @Override
        // 队列里元素的排序依据
        public int compareTo(Delayed o) {
            return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
        }

        @Override
        // 获取剩余时间
        public long getDelay(TimeUnit unit) {
            return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }
    }
}
